/**
* @copyright Copyright (c) 2022-2023 Grab GEO IoT Team
* @file fsmc.h
* @author wenzhu.tu
* @version 0.1
* @date 2023-03-23
* @brief fsmc
*/
#ifndef FSMC_H
#define FSMC_H
/******************************* Includes ********************************/
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#ifndef PC
#include "log_net.h"
#endif
#ifdef __cplusplus
extern "C"
{
#endif

/******************************* Macros ******************************/
#ifndef PC
#define FSMC_TAG ("FSMC-M")
#define FSMC_E(...)  util_loge(FSMC_TAG, __VA_ARGS__)
#define FSMC_I(...)  util_logi(FSMC_TAG, __VA_ARGS__)
#define FSMC_D(...)  util_logd(FSMC_TAG, __VA_ARGS__)
#define FSMC_HEXDUMP(with, buf, len) util_log_hex_dump(FSMC_TAG, with, buf, len)
#else
#define FSMC_E(...)  printf(__VA_ARGS__)
#define FSMC_I(...)  printf(__VA_ARGS__)
#define FSMC_D(...)  printf(__VA_ARGS__)
#endif
#define SCHEDULE_DELAY (1000*1000) //us
/******************************* Typedef ******************************/
typedef void (*action_callback)(int64_t cur_time_ms);

typedef struct fsmc_hanlde
{
   bool loop_run; //false call [run] once
   bool exit_flg;
   action_callback enter;
   action_callback run;
   action_callback exit;   
   struct fsmc_hanlde *last;
   struct fsmc_hanlde *next;
   struct fsmc_hanlde *cur_status;
   pthread_mutex_t mutex;
}fsmc_handle_t;

typedef enum FSMC_ACTION
{
    FSMC_ACTION_LAST,
    FSMC_ACTION_NEXT, 

}FSMC_ACTION_e;

typedef struct fsmc_status_func
{
   bool loop_run; //false call [run] once
   action_callback enter;
   action_callback run;
   action_callback exit;
   int id; 
}fsmc_status_func_t;

/******************************* Variables ******************************/

/******************************* Functions ******************************/

/**
 * @brief fsmc init
 * @return fsmc_handle_t* NULL is fail
 */
fsmc_handle_t *fsmc_init();

/**
 * @brief fsmc deinit
 * @param handle fsmc_handle_t **
 */
void fsmc_deinit(fsmc_handle_t **handle);

/**
 * @brief add fsmc node
 * @param handle fsmc_handle_t *
 * @param node fsmc_status_func_t *
 * @return int -1 error 0 success
 */
int  fsmc_add(fsmc_handle_t *handle, fsmc_status_func_t *node);

/**
 * @brief fsmc action
 * @param handle fsmc_handle_t *
 * @param action FSMC_ACTION_e
 * @return int -1 error 0 success 
 */
int fsmc_action(fsmc_handle_t *handle, FSMC_ACTION_e action);

/**
 * @brief fsmc action
 * @param handle fsmc_handle_t *
 * @param action id index
 * @return int -1 error 0 success 
 */
int fsmc_action_id(fsmc_handle_t *handle, int id);


void fsmc_test();

#ifdef __cplusplus
}
#endif

#endif
/******************************* End of file ******************************/
